﻿using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;

namespace Cloak.Mvvm.Bindings
{
	/// <summary>
	/// A set of bindings between a source object and a view model
	/// </summary>
	public sealed class CompositeBinding : ViewModelBinding
	{
		private readonly IEnumerable<IViewModelBinding> _bindings;

		/// <summary>
		/// Initializes a composite binding with the specified sub-bindings
		/// </summary>
		/// <param name="bindings">The bindings which will all be controlled by this binding</param>
		public CompositeBinding(IEnumerable<IViewModelBinding> bindings)
		{
			Contract.Requires(bindings != null);

			_bindings = bindings;

			foreach(var binding in _bindings)
			{
				binding.IsModifiedChanged += OnBindingIsModifiedChanged;
			}
		}

		/// <summary>
		/// Initializes a composite binding with the specified sub-bindings
		/// </summary>
		/// <param name="bindings">The bindings which will all be controlled by this binding</param>
		public CompositeBinding(params IViewModelBinding[] bindings) : this(bindings as IEnumerable<IViewModelBinding>)
		{}

		/// <summary>
		/// Reads from the source objects and sets values on the view models
		/// </summary>
		protected override void BindFromSourceCore()
		{
			foreach(var binding in _bindings)
			{
				binding.BindFromSource();
			}
		}

		/// <summary>
		/// Reads from the view models and sets values on the source objects
		/// </summary>
		protected override void BindToSourceCore()
		{
			foreach(var binding in _bindings)
			{
				binding.BindToSource();
			}
		}

		private void OnBindingIsModifiedChanged(object sender, EventArgs e)
		{
			IsModified = _bindings.Any(binding => binding.IsModified);
		}
	}
}